home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Database / AddressBook / Controller.m < prev    next >
Text File  |  1995-06-12  |  7KB  |  273 lines

  1. /* Controller.m:
  2.  * You may freely copy, distribute, and reuse the code in this example.
  3.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  4.  * fitness for any particular use.
  5.  *
  6.  * Written by: Mai Nguyen, NeXT Developer Support
  7.  *
  8.  *
  9.  */
  10.  
  11. #import <appkit/appkit.h>
  12. #import <dbkit/dbkit.h>
  13. #import <objc/List.h>
  14. #import <objc/NXBundle.h>
  15. #import <sys/param.h>
  16. #import <libc.h>
  17.  
  18. #import "Controller.h"
  19. #import "AddressView.h"
  20.  
  21.  
  22. #define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when connection to database can't be made")
  23. #define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ")
  24. #define CANNOT_ADD NXLocalizedString("Add operation failed", NULL, "Message given to user that add operation has failed")
  25. #define CANNOT_UPDATE NXLocalizedString("Update operation failed",NULL,"Message given to user that update operation has failed")
  26. #define CANNOT_DELETE NXLocalizedString("Delete operation failed",NULL,"Message given to user that delete operation has failed")
  27.  
  28. @implementation Controller
  29.  
  30. - appDidInit:sender
  31. {
  32.         /* Try to connect to the database specified using the Sybase Adaptor
  33.          * and the default login sa, NULL password, SYBASE server, and
  34.          * pubs database.
  35.          */
  36.        database = [[DBDatabase alloc]init];       
  37.     [database connectUsingAdaptor:"SybaseAdaptor"
  38.                                  andString:"sa@SYBASE/pubs"];
  39.  
  40.     if ( ![database isConnected] ) {
  41.             NXRunAlertPanel(FAILURE, CANNOT_CONNECT, "OK", NULL, NULL);
  42.             return self;
  43.             }
  44.         /* Once successfully connected, build the data to be displayed in the
  45.          * matrix
  46.          */
  47.     [self initRecordList];
  48.     [addressView loadCellsFrom:self];
  49.  
  50.         /* Assign the controller to become the database delegate */
  51.     [database setDelegate:self];
  52.  
  53.        cellMatrix = [addressView cellMatrix];
  54.     
  55.          /* Select a cell as a start */
  56.     [[cellMatrix selectCellAt:0 :0] sendAction];
  57.         /* Bring the main application window up front */
  58.     [theWindow makeKeyAndOrderFront:nil];
  59.                 
  60.        return self;
  61. }
  62.  
  63. /* Set up the DBRecordList object. Create a list of properties which contains
  64.  * all properties needed for display or updating.
  65.  */
  66. - initRecordList
  67. {
  68.     id firstName, lastName, phone;
  69.     id state, city, address, zipCode, contract;
  70.     List    *keyList;
  71.     
  72.     if (recordList)
  73.         [recordList free];
  74.     if (propertyList)
  75.         [propertyList free];
  76.  
  77.             /* get the author table from the database */    
  78.     authorEntity = [database entityNamed:"authors"];
  79.     
  80.             /* get the properties  */
  81.     lastName = [authorEntity propertyNamed:"au_lname"];
  82.     firstName = [authorEntity propertyNamed:"au_fname"];
  83.     authId = [authorEntity propertyNamed:"au_id"];
  84.     
  85.      phone = [authorEntity propertyNamed:"phone"];
  86.     address = [authorEntity propertyNamed:"address"];
  87.     city = [authorEntity propertyNamed:"city"];
  88.     state = [authorEntity propertyNamed:"state"];
  89.     zipCode = [authorEntity propertyNamed:"zip"];      
  90.     contract = [authorEntity propertyNamed:"contract"];
  91.     
  92.           /* Set up the property list 
  93.          * Note that certain properties need to be defined in order
  94.          * for an Insert or Update operation to work. This depends
  95.          * on how your data dictionary has been defined. Here pubs
  96.          * is being used as the model.
  97.          */
  98.     propertyList = [[List alloc] init];
  99.     [propertyList addObject:authId];
  100.       [propertyList addObject:lastName];
  101.     [propertyList addObject:firstName];
  102.       [propertyList addObject:phone];
  103.     [propertyList addObject:address];
  104.     [propertyList addObject:city];
  105.     [propertyList addObject:state];
  106.     [propertyList addObject:zipCode];
  107.       [propertyList addObject:contract];
  108.  
  109.        recordList = [[DBRecordList alloc] init];
  110.     
  111.     
  112.         /* A unique key is needed if you want to update or insert new
  113.          * data via the record list into the database. If no key is defined,
  114.          * the data retrieved via the  record list is read-only.
  115.          * This is needed here, since we do not use a dbmodel to define
  116.          * the key.
  117.          */
  118.     keyList = (List *)[[List alloc] init];
  119.     [keyList addObject:authId];
  120.     [recordList setKeyProperties:keyList];
  121.     [keyList free];
  122.     
  123.     /* You must set the properties FIRST before setting the retrieve order */
  124.     [recordList setProperties:propertyList ofSource:authorEntity];
  125.     
  126.     [recordList addRetrieveOrder:DB_AscendingOrder for:lastName];
  127.     [recordList addRetrieveOrder:DB_AscendingOrder for:firstName];                    
  128.     [recordList fetchUsingQualifier:nil];                                 
  129.        recordCount = [recordList count];
  130.     
  131.        return self;
  132. }
  133.     
  134. /* This method is called when selecting "Insert"
  135.  */
  136. - addRecords:sender
  137. {    
  138.     
  139.     int row;
  140.  
  141.     if (recordCount > 0) {
  142.     
  143.         if ( ![addressView addRecordFrom:sender at:(recordCount-1)]) {
  144.             NXRunAlertPanel(NULL, CANNOT_ADD, NULL, NULL, NULL);
  145.             return self;
  146.         }
  147.         
  148.     [self initRecordList];
  149.      [addressView loadCellsFrom:self];
  150.         /* Find the row of the newly inserted record */
  151.     row = [addressView getNewRow];
  152.        [cellMatrix scrollCellToVisible:row :0];
  153.       [[cellMatrix selectCellAt:row:0] sendAction];
  154.       }
  155.       else
  156.           fprintf(stderr, "empty record list - NOP\n");
  157.       return self;
  158. }
  159.  
  160. /* This method gets called when selecting "Update"
  161.  */
  162. - updateRecords:sender
  163. {
  164.     int row;
  165.     
  166.     row = [cellMatrix selectedRow];
  167.     if ( ![addressView updateRecordFrom:sender at:row]) {
  168.         NXRunAlertPanel(NULL, CANNOT_UPDATE, NULL, NULL, NULL);
  169.         return self;
  170.     }
  171.         /* Redisplay the records */
  172.     [self initRecordList];
  173.      [addressView loadCellsFrom:self];
  174.         /* find the row of the updated record */
  175.     row = [addressView getNewRow];
  176.        [cellMatrix scrollCellToVisible:row :0];
  177.       [[cellMatrix selectCellAt:row:0] sendAction];
  178.  
  179.     return self;
  180. }
  181.  
  182.  
  183. - deleteRecords:sender
  184. {    
  185.     
  186.     int row;
  187.     
  188.     row = [cellMatrix selectedRow];
  189.     if (recordCount > 0) {
  190.     
  191.     if (![addressView deleteSelectedRecord:sender]) {
  192.             NXRunAlertPanel(NULL, CANNOT_DELETE, NULL, NULL, NULL);
  193.             return self;
  194.         }
  195.  
  196.     [self initRecordList];
  197.      [addressView loadCellsFrom:self];
  198.        [cellMatrix scrollCellToVisible:row :0];
  199.       [[cellMatrix selectCellAt:row:0] sendAction];
  200.       }
  201.       else
  202.           fprintf(stderr, "empty record list - NOP\n");
  203.     
  204.     return self;
  205. }    
  206. - getRecordList
  207. {
  208.     return recordList;
  209. }
  210.  
  211. - getPropertyList
  212. {
  213.     return propertyList;
  214. }
  215.  
  216. - (int)getRecordCount
  217. {
  218.     return recordCount;
  219. }
  220.  
  221. - showSQLPanel:sender
  222. {
  223.     [SQLPanel makeKeyAndOrderFront:nil];
  224.     return self;
  225. }
  226.  
  227. - showInfoPanel:sender
  228. {
  229.     if (!infoPanel) {
  230.         infoPanel = [NXApp loadNibSection:"InfoPanel.nib" owner:NXApp
  231.                                                          withNames:NO]; 
  232.         }
  233.     [infoPanel orderFront:nil];
  234.     return self;
  235. }
  236.  
  237. - appWillTerminate:sender
  238. {
  239.     /* deallocate what has been allocated */
  240.     if (recordList)
  241.         [recordList free];
  242.     if (propertyList)
  243.         [propertyList free];
  244.     return self;
  245. }
  246.  
  247. /* DBDatabase delegate methods to log error messages and SQL queries */
  248.  
  249. - (BOOL)db:aDb willEvaluateString:(const unsigned char*)aString
  250.      usingBinder:aBinder
  251. {
  252.     [textObj appendToText:"SQL Query:\n"];
  253.     [textObj appendToText:aString];
  254.     [textObj appendToText:"\n"];
  255.     return YES;
  256. }
  257.  
  258. @end
  259.  
  260. @implementation Text(printResults)
  261.  
  262. - appendToText:(const char *)newText
  263. {
  264.     int currentLength = [self textLength];
  265.  
  266.     [self setSel:currentLength :currentLength];
  267.     [self replaceSel:newText];
  268.     [self scrollSelToVisible];
  269.     return self;
  270. }
  271.  
  272. @end
  273.